package com.swsc.solarverse.service.schedule;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.swsc.solarverse.common.config.ResParams;
import com.swsc.solarverse.common.enums.DeviceSourceEnums;
import com.swsc.solarverse.common.enums.DeviceTypeEnums;
import com.swsc.solarverse.common.util.ObjectMapper;
import com.swsc.solarverse.common.util.RegexUtils;
import com.swsc.solarverse.dao.entity.analysis.StringEfficiencyRecordDO;
import com.swsc.solarverse.dao.entity.forward.ForwardDeviceInfoDO;
import com.swsc.solarverse.dao.entity.forward.ForwardStringDataCurrentdayDO;
import com.swsc.solarverse.dao.entity.forward.ForwardStringDataDO;
import com.swsc.solarverse.dao.entity.sys.CorporationDO;
import com.swsc.solarverse.dao.mapper.CustomSqlMapper;
import com.swsc.solarverse.service.analysis.ICorporationEfficiencyRecordService;
import com.swsc.solarverse.service.analysis.IStringEfficiencyRecordService;
import com.swsc.solarverse.service.common.ForwardDeviceDataHelper;
import com.swsc.solarverse.service.forward.IForwardDeviceInfoService;
import com.swsc.solarverse.service.forward.IForwardStringDataCurrentdayService;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author chencl
 * @Date 2024/7/22 9:35
 * @Version 1.0
 * @Description 组串能效计算
 */
@lombok.extern.slf4j.Slf4j
@org.springframework.stereotype.Service
public class StringEfficiencyRecordAnalysisService {
    private final IForwardDeviceInfoService forwardDeviceInfoService;
    private final IStringEfficiencyRecordService stringEfficiencyRecordService;
    private final ICorporationEfficiencyRecordService corporationEfficiencyRecordService;

    private final IForwardStringDataCurrentdayService forwardStringDataCurrentdayService;
    private final CustomSqlMapper customSqlMapper;

    public StringEfficiencyRecordAnalysisService(IForwardDeviceInfoService forwardDeviceInfoService,
                                                 IStringEfficiencyRecordService stringEfficiencyRecordService,
                                                 ICorporationEfficiencyRecordService corporationEfficiencyRecordService,
                                                 IForwardStringDataCurrentdayService forwardStringDataCurrentdayService,
                                                 CustomSqlMapper customSqlMapper) {
        this.forwardDeviceInfoService = forwardDeviceInfoService;
        this.stringEfficiencyRecordService = stringEfficiencyRecordService;
        this.corporationEfficiencyRecordService = corporationEfficiencyRecordService;
        this.forwardStringDataCurrentdayService = forwardStringDataCurrentdayService;
        this.customSqlMapper = customSqlMapper;
    }

    /**
     * 组串能效计算 取9-15点数据, 每分钟一条进行积分计算
     *
     * @param corporationDo
     * @param dataTime
     * @param dateTime
     */
    public void analysisStationStringDataNew(CorporationDO corporationDo, LocalDateTime dataTime, LocalDateTime dateTime) {
        if (null == corporationDo || null == dataTime || null == dateTime) {
            return;
        }
        List<ForwardDeviceInfoDO> forwardDeviceInfoDos = forwardDeviceInfoService.list(Wrappers.lambdaQuery(ForwardDeviceInfoDO.class)
                .eq(ForwardDeviceInfoDO::getTenantNo, corporationDo.getTenantNo())
                .eq(ForwardDeviceInfoDO::getOrganNo, corporationDo.getOrganNo())
                .eq(ForwardDeviceInfoDO::getDeviceSource, DeviceSourceEnums.SCADA.getCode())
                .in(ForwardDeviceInfoDO::getDeviceType, Arrays.asList(DeviceTypeEnums.INVERTER.getType(), DeviceTypeEnums.COMBINER_BOX.getType(), DeviceTypeEnums.STRR.getType()))
        );
        log.info("低效组串发电量计算-查询所有设备信息: {}, {}", corporationDo.getOrganNo(), forwardDeviceInfoDos.size());
        if (CollectionUtils.isEmpty(forwardDeviceInfoDos)) {
            log.info("低效组串发电量计算-未查询到设备信息: {}, {}", corporationDo.getOrganNo(), forwardDeviceInfoDos.size());
            return;
        }
        List<ForwardDeviceInfoDO> inverterForwardDeviceInfoDos = forwardDeviceInfoDos.stream().filter(fdid -> DeviceTypeEnums.INVERTER.getType().equals(fdid.getDeviceType())).collect(Collectors.toList());
        log.info("低效组串发电量计算-查询到逆变器设备数量: {}, {}", corporationDo.getOrganNo(), inverterForwardDeviceInfoDos.size());
        List<ForwardDeviceInfoDO> combinerboxForwardDeviceInfoDos = forwardDeviceInfoDos.stream().filter(fdid -> DeviceTypeEnums.COMBINER_BOX.getType().equals(fdid.getDeviceType())).collect(Collectors.toList());
        log.info("低效组串发电量计算-查询到汇流箱设备数量: {}, {}", corporationDo.getOrganNo(), combinerboxForwardDeviceInfoDos.size());
        List<ForwardDeviceInfoDO> stringForwardDeviceInfoDos = forwardDeviceInfoDos.stream().filter(fdid -> DeviceTypeEnums.STRR.getType().equals(fdid.getDeviceType())).collect(Collectors.toList());
        log.info("低效组串发电量计算-查询到组串设备数量: {}, {}", corporationDo.getOrganNo(), stringForwardDeviceInfoDos.size());
        List<StringEfficiencyRecordDO> efficiencyRecordResults = new ArrayList<>(forwardDeviceInfoDos.size() * 18);
        if (CollectionUtils.isNotEmpty(inverterForwardDeviceInfoDos)) {
            // 逆变器按照子阵分组
            Map<String, List<ForwardDeviceInfoDO>> submatrixInverterForwardDeviceMap = inverterForwardDeviceInfoDos.stream().collect(Collectors.groupingBy(fdid -> RegexUtils.extractInverterSubmatrixCode(fdid.getDeviceCode())));
            List<StringEfficiencyRecordDO> inverterStringEfficiencyRecordResults = processSubmatrixForwardDeviceMap(corporationDo, submatrixInverterForwardDeviceMap, DeviceTypeEnums.INVERTER, dataTime, dateTime);
            if (CollectionUtils.isNotEmpty(inverterStringEfficiencyRecordResults)) {
                efficiencyRecordResults.addAll(inverterStringEfficiencyRecordResults);
            }
        }
        if (CollectionUtils.isNotEmpty(combinerboxForwardDeviceInfoDos)) {
            // 汇流箱按照子阵分组
            Map<String, List<ForwardDeviceInfoDO>> submatrixCombinerboxForwardDeviceMap = combinerboxForwardDeviceInfoDos.stream().collect(Collectors.groupingBy(fdid -> RegexUtils.extractSubmatrixCode(fdid.getDeviceCode())));
            List<StringEfficiencyRecordDO> combinerboxStringEfficiencyRecordResults = processSubmatrixForwardDeviceMap(corporationDo, submatrixCombinerboxForwardDeviceMap, DeviceTypeEnums.COMBINER_BOX, dataTime, dateTime);
            if (CollectionUtils.isNotEmpty(combinerboxStringEfficiencyRecordResults)) {
                efficiencyRecordResults.addAll(combinerboxStringEfficiencyRecordResults);
            }
        }
        if (CollectionUtils.isNotEmpty(stringForwardDeviceInfoDos)) {
            // 组串按照子阵分组
            Map<String, List<ForwardDeviceInfoDO>> submatrixStringForwardDeviceMap = stringForwardDeviceInfoDos.stream()
                    .collect(Collectors.groupingBy(fdid -> (StringUtils.isNotBlank(fdid.getZone()) ? fdid.getZone() : RegexUtils.extractSubmatrixCode(fdid.getDeviceCode()))));
            List<StringEfficiencyRecordDO> strStringEfficiencyRecordResults = processSubmatrixForwardDeviceMap(corporationDo, submatrixStringForwardDeviceMap, DeviceTypeEnums.STRR, dataTime, dateTime);
            if (CollectionUtils.isNotEmpty(strStringEfficiencyRecordResults)) {
                efficiencyRecordResults.addAll(strStringEfficiencyRecordResults);
            }
        }
        if (CollectionUtils.isNotEmpty(efficiencyRecordResults)) {
            efficiencyRecordResults.sort(new Comparator<StringEfficiencyRecordDO>() {
                @Override
                public int compare(StringEfficiencyRecordDO o1, StringEfficiencyRecordDO o2) {
                    return o1.getDeviceCode().compareTo(o2.getDeviceCode());
                }
            });
        }
        // 同一子阵逆变器-组串和汇流箱-字串不会混搭
        if (CollectionUtils.isNotEmpty(efficiencyRecordResults)) {
            log.info("低效组串发电量计算-保存结果数据开始: {}", efficiencyRecordResults.size());
            int cnt = stringEfficiencyRecordService.insertIgnoreBatch(efficiencyRecordResults);
            log.info("低效组串发电量计算-保存结果数据结束: {}", cnt);
        } else {
            log.info("低效组串发电量计算-无数据保存");
        }

    }

    public List<StringEfficiencyRecordDO> processSubmatrixForwardDeviceMap(CorporationDO corporationDo, Map<String, List<ForwardDeviceInfoDO>> submatrixForwardDeviceMap,
                                                                           DeviceTypeEnums deviceTypeEnum, LocalDateTime dataTime, LocalDateTime dateTime) {
        if (null != corporationDo && null != submatrixForwardDeviceMap && submatrixForwardDeviceMap.size() > 0) {
            if (null == deviceTypeEnum) {
                deviceTypeEnum = DeviceTypeEnums.INVERTER;
            }
            LocalDateTime dateTimeGe = dataTime.withHour(9).withMinute(0).withSecond(0).withNano(0);
            LocalDateTime dateTimeLt = dataTime.withHour(15).withMinute(1).withSecond(0).withNano(0);
            List<StringEfficiencyRecordDO> efficiencyRecordResults = new ArrayList<>(submatrixForwardDeviceMap.size() * 18);
            if (DeviceTypeEnums.INVERTER == deviceTypeEnum) {
                for (Map.Entry<String, List<ForwardDeviceInfoDO>> submatrixForwardDeviceMapEntry : submatrixForwardDeviceMap.entrySet()) {
                    if (ResParams.collectingDistributingSubmatrixCodes().contains(submatrixForwardDeviceMapEntry.getKey())) {
                        log.info("低效组串发电量计算-该子阵为集散式逆变器: {}", submatrixForwardDeviceMapEntry.getKey());
                        continue;
                    }
                    List<String> deviceUidIn = submatrixForwardDeviceMapEntry.getValue().stream().map(ForwardDeviceInfoDO::getDeviceUid).collect(Collectors.toList());
                    List<Map<String, Object>> submatrixInverterDataList = null; //customSqlMapper.queryInverterDataByTmstampRange(deviceUidIn, dateTimeGe, dateTimeLt);
                    log.info("低效组串发电量计算-查询逆变器设备电压电流数据: {}, {}, {}", corporationDo.getOrganNo(), submatrixForwardDeviceMapEntry.getKey(), null != submatrixInverterDataList ? submatrixInverterDataList.size() : 0);
                    if (CollectionUtils.isEmpty(submatrixInverterDataList)) {
                        log.info("低效组串发电量计算-未查询到逆变器设备电压电流数据: {}, {}", corporationDo.getOrganNo(), submatrixForwardDeviceMapEntry.getKey());
                        continue;
                    }
                    List<ForwardStringDataDO> submatrixForwardStringDataDos = ForwardDeviceDataHelper.processInverterData(submatrixForwardDeviceMapEntry.getValue(), submatrixInverterDataList, dateTime);
                    log.info("低效组串发电量计算-转换逆变器设备电压电流数据: {}, {}, {}", corporationDo.getOrganNo(), submatrixForwardDeviceMapEntry.getKey(), submatrixForwardStringDataDos.size());
                    if (CollectionUtils.isEmpty(submatrixForwardStringDataDos)) {
                        log.info("低效组串发电量计算-转换逆变器设备电压电流数据后无数据: {}, {}", corporationDo.getOrganNo(), submatrixForwardDeviceMapEntry.getKey());
                        continue;
                    }
                    // 计算组串能效
                    ForwardDeviceDataHelper.calculateStringEfficiencyRecordBySubmatrix(corporationDo.getOrganNo(), submatrixForwardDeviceMapEntry.getKey(), dataTime, dateTime,
                            submatrixForwardStringDataDos, efficiencyRecordResults);
                }
            } else if (DeviceTypeEnums.COMBINER_BOX == deviceTypeEnum) {
                for (Map.Entry<String, List<ForwardDeviceInfoDO>> submatrixForwardDeviceMapEntry : submatrixForwardDeviceMap.entrySet()) {
                    List<String> deviceUidIn = submatrixForwardDeviceMapEntry.getValue().stream().map(ForwardDeviceInfoDO::getDeviceUid).collect(Collectors.toList());
                    List<Map<String, Object>> submatrixCombinerboxDataList = null; //customSqlMapper.queryCombinerboxDataByTmstampRange(deviceUidIn, dateTimeGe, dateTimeLt);
                    log.info("低效组串发电量计算-查询汇流箱设备电压电流数据: {}, {}, {}", corporationDo.getOrganNo(), submatrixForwardDeviceMapEntry.getKey(), null != submatrixCombinerboxDataList ? submatrixCombinerboxDataList.size() : 0);
                    if (CollectionUtils.isEmpty(submatrixCombinerboxDataList)) {
                        log.info("低效组串发电量计算-未查询到汇流箱设备电压电流数据: {}, {}", corporationDo.getOrganNo(), submatrixForwardDeviceMapEntry.getKey());
                        continue;
                    }
                    List<ForwardStringDataDO> submatrixForwardStringDataDos = ForwardDeviceDataHelper.processCombinerboxData(submatrixForwardDeviceMapEntry.getValue(), submatrixCombinerboxDataList, dateTime);
                    log.info("低效组串发电量计算-转换汇流箱设备电压电流数据: {}, {}, {}", corporationDo.getOrganNo(), submatrixForwardDeviceMapEntry.getKey(), submatrixForwardStringDataDos.size());
                    if (CollectionUtils.isEmpty(submatrixForwardStringDataDos)) {
                        log.info("低效组串发电量计算-转换汇流箱设备电压电流数据后无数据: {}, {}", corporationDo.getOrganNo(), submatrixForwardDeviceMapEntry.getKey());
                        continue;
                    }
                    // 计算组串能效
                    ForwardDeviceDataHelper.calculateStringEfficiencyRecordBySubmatrix(corporationDo.getOrganNo(), submatrixForwardDeviceMapEntry.getKey(), dataTime, dateTime,
                            submatrixForwardStringDataDos, efficiencyRecordResults);
                }
            } else if (DeviceTypeEnums.STRR == deviceTypeEnum) {
                for (Map.Entry<String, List<ForwardDeviceInfoDO>> submatrixForwardDeviceMapEntry : submatrixForwardDeviceMap.entrySet()) {
                    List<Long> devicePidIn = submatrixForwardDeviceMapEntry.getValue().stream().map(ForwardDeviceInfoDO::getDevicePid).collect(Collectors.toList());
                    List<ForwardStringDataCurrentdayDO> stringDataCurrentdayDos = forwardStringDataCurrentdayService.list(Wrappers.lambdaQuery(ForwardStringDataCurrentdayDO.class)
                            .eq(ForwardStringDataCurrentdayDO::getTenantNo, corporationDo.getTenantNo())
                            .eq(ForwardStringDataCurrentdayDO::getOrganNo, corporationDo.getOrganNo())
                            .in(ForwardStringDataCurrentdayDO::getDevicePid, devicePidIn)
                            .ge(ForwardStringDataCurrentdayDO::getDataTime, dateTimeGe)
                            .lt(ForwardStringDataCurrentdayDO::getDataTime, dateTimeLt)
                    );
                    log.info("低效组串发电量计算-查询组串设备电压电流数据: {}, {}, {}", corporationDo.getOrganNo(), submatrixForwardDeviceMapEntry.getKey(), stringDataCurrentdayDos.size());
                    if (CollectionUtils.isEmpty(stringDataCurrentdayDos)) {
                        log.info("低效组串发电量计算-未查询到组串设备电压电流数据: {}, {}", corporationDo.getOrganNo(), submatrixForwardDeviceMapEntry.getKey());
                        continue;
                    }
                    List<ForwardStringDataDO> submatrixForwardStringDataDos = ObjectMapper.mapList(stringDataCurrentdayDos, ForwardStringDataDO.class);
                    log.info("低效组串发电量计算-转换组串设备电压电流数据: {}, {}, {}", corporationDo.getOrganNo(), submatrixForwardDeviceMapEntry.getKey(), submatrixForwardStringDataDos.size());
                    if (CollectionUtils.isEmpty(submatrixForwardStringDataDos)) {
                        log.info("低效组串发电量计算-转换组串设备电压电流数据后无数据: {}, {}", corporationDo.getOrganNo(), submatrixForwardDeviceMapEntry.getKey());
                        continue;
                    }
                    // 计算组串能效
                    ForwardDeviceDataHelper.calculateStringEfficiencyRecordBySubmatrix(corporationDo.getOrganNo(), submatrixForwardDeviceMapEntry.getKey(), dataTime, dateTime,
                            submatrixForwardStringDataDos, efficiencyRecordResults);
                }
            }
            return efficiencyRecordResults;
        }

        return null;
    }

}
